我使用以下代码来消耗USE THIS IMAGE LOADER EXTENSION
let imageCache = NSCache<AnyObject, AnyObject>()
class ImageLoader: UIImageView {
var imageURL: URL?
let activityIndicator = UIActivityIndicatorView()
func loadImageWithUrl(_ url: URL) {
// setup activityIndicator...
activityIndicator.color = .darkGray
addSubview(activityIndicator)
activityIndicator.translatesAutoresizingMaskIntoConstraints = false
activityIndicator.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
activityIndicator.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
imageURL = url
image = nil
activityIndicator.startAnimating()
// retrieves image if already available in cache
if let imageFromCache = imageCache.object(forKey: url as AnyObject) as? UIImage {
self.image = imageFromCache
activityIndicator.stopAnimating()
return
}
// image does not available in cache.. so retrieving it from url...
URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in
if error != nil {
print(error as Any)
self.activityIndicator.stopAnimating()
return
}
DispatchQueue.main.async(execute: {
if let unwrappedData = data, let imageToCache = UIImage(data: unwrappedData) {
if self.imageURL == url {
self.image = imageToCache
}
imageCache.setObject(imageToCache, forKey: url as AnyObject)
}
self.activityIndicator.stopAnimating()
})
}).resume()
}
}
** design controller **
import UIKit
class ImageController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
private let cellId = "cellId"
lazy var imagesSliderCV: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.translatesAutoresizingMaskIntoConstraints = false
cv.backgroundColor = .white
cv.showsHorizontalScrollIndicator = false
cv.delegate = self
cv.dataSource = self
cv.isPagingEnabled = true
cv.register(ImageSliderCell.self, forCellWithReuseIdentifier: self.cellId)
return cv
}()
//
// Mark:- CollectionView Methods........
//
var arrURLs = [
"https://homepages.cae.wisc.edu/~ece533/images/airplane.png",
"https://homepages.cae.wisc.edu/~ece533/images/arctichare.png",
"https://homepages.cae.wisc.edu/~ece533/images/baboon.png",
"https://homepages.cae.wisc.edu/~ece533/images/barbara.png",
"https://homepages.cae.wisc.edu/~ece533/images/boat.png",
"https://homepages.cae.wisc.edu/~ece533/images/cat.png",
"https://homepages.cae.wisc.edu/~ece533/images/fruits.png",
"https://homepages.cae.wisc.edu/~ece533/images/frymire.png",
"https://homepages.cae.wisc.edu/~ece533/images/girl.png",
"https://homepages.cae.wisc.edu/~ece533/images/goldhill.png",
"https://homepages.cae.wisc.edu/~ece533/images/lena.png",
"https://homepages.cae.wisc.edu/~ece533/images/monarch.png",
"https://homepages.cae.wisc.edu/~ece533/images/mountain.png",
"https://homepages.cae.wisc.edu/~ece533/images/peppers.png",
"https://homepages.cae.wisc.edu/~ece533/images/pool.png",
"https://homepages.cae.wisc.edu/~ece533/images/sails.png",
"https://homepages.cae.wisc.edu/~ece533/images/serrano.png",
"https://homepages.cae.wisc.edu/~ece533/images/tulips.png",
"https://homepages.cae.wisc.edu/~ece533/images/watch.png",
"https://homepages.cae.wisc.edu/~ece533/images/zelda.png"
]
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return arrURLs.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! ImageSliderCell
let ImagePath = arrURLs[indexPath.item]
if let strUrl = ImagePath.addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed),
let imgUrl = URL(string: strUrl) {
cell.frontImg.loadImageWithUrl(imgUrl)
}
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: screenWidth, height: 288)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func setupAutoLayout(){
NSLayoutConstraint.activate([
imagesSliderCV.leftAnchor.constraint(equalTo: view.leftAnchor),
imagesSliderCV.rightAnchor.constraint(equalTo: view.rightAnchor),
imagesSliderCV.topAnchor.constraint(equalTo: view.topAnchor),
imagesSliderCV.bottomAnchor.constraint(equalTo: view.bottomAnchor),
])
}
}
**collectionView cell **
import UIKit
class ImageSliderCell: UICollectionViewCell {
//
let frontImg: ImageLoader = {
let img = ImageLoader()
img.translatesAutoresizingMaskIntoConstraints = false
img.contentMode = .scaleAspectFill
img.clipsToBounds = true
return img
}()
//
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(frontImg)
setupAutolayout()
}
func setupAutolayout(){
frontImg.leftAnchor.constraint(equalTo: leftAnchor, constant: 8).isActive = true
frontImg.rightAnchor.constraint(equalTo: rightAnchor, constant: -8).isActive = true
frontImg.topAnchor.constraint(equalTo: topAnchor, constant: 8).isActive = true
frontImg.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8).isActive = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
。但是我无法为文件指定multipart/form-data
。春季如何传递content-type
,文件名,文件名内容?
content-type
我使用MultiValueMap添加文件名及其内容,但我无法传递文件的内容类型。 执行时,我收到400错误请求。你可以在这里帮忙吗?
我以前尝试过以下方法,这里也收到了400个错误请求。这里需要帮助。
HttpHeaders header = new HttpHeaders();
header.add("Token", "_45378ffb-e366-45ec-9ac4-eb968c57aee3"); header.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, Object> fileMap = new LinkedMultiValueMap<>();
fileMap.add(filename, msg.getBytes());
fileMap.add("OrderRequest", message);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<MultiValueMap<String, Object>>(fileMap, header);
ResponseEntity<String> response = restTemplate.postForEntity(url, requestEntity,String.class);
答案 0 :(得分:0)
准备文件部分
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
var m = 10,
r = 100,
z = d3.scale.category20c();
var pie = d3.layout.pie()
.value(function(d) { return +d.qty; })
.sort(function(a, b) { return b.qty - a.qty;});
然后准备消息部分
HttpHeaders filePartHeaders = new HttpHeaders();
filePartHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
HttpEntity filePart = new HttpEntity<>(new ByteArrayResource(msg.getBytes()) {
@Override
public String getFilename() {
return filename;
}
}, filePartHeaders);
然后将各个部分组合成一个多部分请求实体
HttpHeaders messagePartHeaders = new HttpHeaders();
messagePartHeaders.setContentType(MediaType.TEXT_PLAIN);
HttpEntity messagePart = new HttpEntity<>(message, messagePartHeaders);
最后执行请求
HttpHeaders header = new HttpHeaders();
header.add("Token", "_45378ffb-e366-45ec-9ac4-eb968c57aee3");
header.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, Object> multiMap = new LinkedMultiValueMap<>();
multiMap.add(filename, filePart);
multiMap.add("OrderRequest", messagePart);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(multiMap, header);
答案 1 :(得分:0)
谢谢你, 我尝试过,但再次收到400错误请求。在这里,我使用了tcpdump并得到了这样的响应:
POST XXXXXXXXXXXXXXXXXXXXX
Accept: text/plain, application/json, application/*+json, */*
Content-Type: multipart/form-data;charset=UTF-8;boundary=XXXXXXXXXXXXXXXX
Token: XXXXXXXXXXXXXXXXXXXXXXXXXXX
User-Agent: Java/1.8.0_201
Host: XXXXXXXXXXXXXXXXXXXXXXXXXX
Connection: keep-alive
Content-Length: 1003
�bA]fG
�k�?A�--XXXXXXXXXXXXXXXXXXXX
Content-Disposition: form-data; name=filename; filename=fileName
Content-Type: application/octet-stream
Content-Length: 511
MSH|^~\&|GHHHH v2012007|HL93765411|GHH|DHM|20170725121244||ORM^O01|ghjk09876|P|2.3.1|6||AL|NE|AU|||
PID|1|||11057^^^GPC Test Practice^MR^GPC Test Practice|XXX^XXX^^^jjj^^L||19920321|F|||188 HEIGHTS DR^^ROBINA^QLD^4226^^C|||^ORN^PH^^^^04
01817188^||||||||||||||||
PV1|1|O||||||2121331W^BHAR^NAV^^^MR.^^^AUSHICPR|2121331W^BHAR^NAV^^^MR.^^^AUSHICPR|||||||||||
ORC|NW|10188-1||10188||||||||^Admin^Mr.
OBR|1|10188-1||T001^Histopathology^LN|||201707251212||||L|||||^Admin^Mr.||||||||LAB
BLG||F
--XXXXXXXXXXXXXXXXXX
Content-Disposition: form-data; name="FileName1"
Content-Type: application/json
Content-Length: 133
{"client_software_version":"XXX","batch_id":"XXXXX","order_files_sent":["fileName"],"client_software_name":"XXXXX"}
--XXXXXXXXXXXX--
以下响应是其余模板的预期响应。在这里需要帮助。 对于下面的tcpdump响应和我们不使用rest模板而获得的响应,它的工作方式是:
POST XXXXXXXXXXXXXXXXX
token: XXXXXXXXXXXXXXXXXXXXXXXXXX
content-type: multipart/form-data; boundary="---boundary"
Content-Length: 940
Host: XXXXXXXXXXXXXXXXXXXXXXXXXXXX
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.3 (Java/1.8.0_201)
Accept-Encoding: gzip,deflate
-----boundary
Content-Disposition: form-data; name="fileName"; filename="fileName"
Content-Type: application/octet-stream
MSH|^~\&|GHHHH v2012007|HL93765411|GHH|DHM|20170725121244||ORM^O01|ghjk09876|P|2.3.1|6||AL|NE|AU|||
PID|1|||11057^^^GPC Test Practice^MR^GPC Test Practice|XXX^XXX^^^jjj^^L||19920321|F|||188 HEIGHTS DR^^ROBINA^QLD^4226^^C|||^ORN^PH^^^^04
01817188^||||||||||||||||
PV1|1|O||||||2121331W^BHAR^NAV^^^MR.^^^AUSHICPR|2121331W^BHAR^NAV^^^MR.^^^AUSHICPR|||||||||||
ORC|NW|10188-1||10188||||||||^Admin^Mr.
OBR|1|10188-1||T001^Histopathology^LN|||201707251212||||L|||||^Admin^Mr.||||||||LAB
BLG||F
-----boundary
Content-Disposition: form-data; name="filename1"; filename="filename1"
Content-Type: application/json; charset=UTF-8
{"client_software_version":"XXX","batch_id":"XXXXX","order_files_sent":["fileName"],"client_software_name":"XXXXX"}
-----boundary--