Spring for Android,文件上传进度

Dam*_*zak 7 rest spring android file-upload

我正在使用Spring for Android作为Android应用程序中远程调用的REST模板.

目前正致力于将图像上传到服务器.

我想出了类似的东西:

public Picture uploadPicture(String accessToken, String fileToUpload) throws RestClientException {
    RestTemplate rest = new RestTemplate();
    FormHttpMessageConverter formConverter = new FormHttpMessageConverter();
    formConverter.setCharset(Charset.forName("UTF8"));
    CustomGsonHttpMessageConverter jsonConverter = new CustomGsonHttpMessageConverter();
    rest.getMessageConverters().add(formConverter);
    rest.getMessageConverters().add(jsonConverter);
    String uploadUri = AppConfig.ROOT_URL.concat(AppConfig.ADD_PHOTO);

    HashMap<String, Object> urlVariables = new HashMap<String, Object>();
    urlVariables.put("accessToken", accessToken);

    HttpHeaders httpHeaders = new HttpHeaders();
    httpHeaders.setAccept(Collections.singletonList(MediaType.parseMediaType("application/json")));

    MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>();
    parts.add("picture", new FileSystemResource(fileToUpload));
    Picture response = rest.postForObject(uploadUri, parts, Picture.class, urlVariables);
    return response;
}
Run Code Online (Sandbox Code Playgroud)

哪个工作正常,但现在我想从中获取进度更新.

有谁知道它是否可能以及如何做到这一点?

提前致谢 :)

Dav*_*ves 3

所以我遇到了同样的问题,并决定研究一下 Spring-Android 源代码。经过大量挖掘后,我发现我需要扩展什么。从这个链接中得到了我的一些灵感。

进度监听器

public interface ProgressListener {
  void transferred(long num);
}
Run Code Online (Sandbox Code Playgroud)

计数输入流

public class CountingInputStream extends FileInputStream {

 private final ProgressListener listener;
 private long transferred;

 public CountingInputStream(File file, ProgressListener listener) throws FileNotFoundException {
    super(file);
    this.listener = listener;
    this.transferred = 0;
 }

 @Override
 public int read(byte[] buffer) throws IOException {
    int bytesRead = super.read(buffer);
    if (bytesRead != -1) {
        this.transferred += bytesRead;
    }
    this.listener.transferred(this.transferred);
    return bytesRead;
 }

}
Run Code Online (Sandbox Code Playgroud)

监听器文件系统资源

public class ListenerFileSystemResource extends FileSystemResource {

 private final ProgressListener listener;

 public ListenerFileSystemResource(File file, ProgressListener listener) {
     super(file);
     this.listener = listener;
 }

 @Override
 public InputStream getInputStream() throws IOException {
     return new CountingInputStream(super.getFile(), listener);
 }

}
Run Code Online (Sandbox Code Playgroud)

发送文件任务

private class SendFileTask extends AsyncTask<String, Integer, Boolean> {
    private ProgressListener listener;
    private long totalSize;

    @Override
    protected Boolean doInBackground(String... params) {
        File file = new File(filePath);
        totalSize = file.length();
        listener = new ProgressListener() {
            @Override
            public void transferred(long num) {
                publishProgress((int) ((num / (float) totalSize) * 100));
            }
        };
        ListenerFileSystemResource resource = new ListenerFileSystemResource(file, listener);
        MyResult result = new MyService().uploadFile(resource);
    }
Run Code Online (Sandbox Code Playgroud)

我的服务

public FileResult uploadFile(ListenerFileSystemResource resource, Long userId, FileType type) {
    String[] pathParams = {ConnectorConstants.FILE_RESOURCE };
    String[] headerKeys = {"manager_user_id"};
    String[] headerValues = {String.valueOf(userId)};
    String[] formKeys = {ConnectorConstants.FILE_FORM_PARAM};
    Object[] formValues = {resource};

    MultiValueMap<String, Object> body = createMultiValueMap(formKeys, formValues);

    HttpConnector<FileResult> connector = new HttpConnector<FileResult>(FileResult.class);
    return connector.path(pathParams).header(createValuePairs(headerKeys, headerValues)).multipart().body(body).post();
}
Run Code Online (Sandbox Code Playgroud)

Http连接器

public final class HttpConnector<T> {

    public static String API_URL = "https://myapi.com";

    private UriComponentsBuilder builder;

    private RestTemplate template;

    private Class<T> generic;

    private HttpEntity<?> requestEntity;

    private HttpHeaders headers;

    /**
     * 
     * @param generic
     */
    protected HttpConnector(Class<T> generic)
    {
            this.builder = UriComponentsBuilder.fromUriString(API_URL);
            this.template = new RestTemplate();
    this.template.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
            this.generic = generic;
            this.template.getMessageConverters().add(new GsonHttpMessageConverter(getGson()));
            this.headers = new HttpHeaders();
    }

    /**
     * 
     * @param pathSegments
     * @return
     */
    protected HttpConnector<T> path(String[] pathSegments)
    {
            this.builder = builder.pathSegment(pathSegments);
            return this;
    }

    /**
     * 
     * @param headerParams
     * @return
     */
    protected HttpConnector<T> header(List<NameValuePair> headerParams)
    {
            for (NameValuePair param : headerParams)
            {
                    headers.add(param.getName(), param.getValue());
            }
            return this;
    }

    /**
     * 
     * @param queryParams
     * @return
     */
    protected HttpConnector<T> query(List<NameValuePair> queryParams)
    {
            for (NameValuePair param : queryParams)
            {
                    this.builder = builder.queryParam(param.getName(), param.getValue());
            }
            return this;
    }

    /**
     * 
     * @param body
     * @return
     */
    protected HttpConnector<T> body(MultiValueMap<String, ? extends Object> body)
    {
            this.requestEntity = new HttpEntity<Object>(body, headers);
            return this;
    }

    /**
     * 
     * @param body
     * @return
     */
    protected HttpConnector<T> body(Object body)
    {
            this.requestEntity = new HttpEntity<Object>(body, headers);
            headers.setContentType(MediaType.APPLICATION_JSON);
            return this;
    }

    /**
     * 
     * @return
     */
    protected HttpConnector<T> form()
    {
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            return addFormConverter();
    }

    /**
     * 
     * @return
     */
    protected HttpConnector<T> multipart()
    {
            headers.setContentType(MediaType.MULTIPART_FORM_DATA);
            return addFormConverter();
    }

    /**
     * 
     * @return
     */
    private HttpConnector<T> addFormConverter()
    {
            this.template.getMessageConverters().add(new FormHttpMessageConverter());
            return this;
    }

    /**
     * 
     * @return
     * @throws MeplisNotFoundException 
     */
    protected T post() throws MeplisNotFoundException
    {
            return sendRequest(HttpMethod.POST);
    }

    /**
     * 
     * @return
     * @throws MeplisNotFoundException 
     */
    protected T put() throws MeplisNotFoundException
    {
            return sendRequest(HttpMethod.PUT);
    }

    /**
     * 
     * @return
     * @throws MeplisNotFoundException 
     */
    protected T get() throws MeplisNotFoundException
    {
            return sendRequest(HttpMethod.GET);
    }

    /**
     * 
     * @param method
     * @return
     * @throws MeplisNotFoundException 
     */
    private T sendRequest(HttpMethod method) throws MyServiceNotFoundException
    {
            HttpStatus status = null;
            ResponseEntity<T> response;
            try
            {
                    response = template.exchange(toUri(), method, getRequestEntity(), generic);
                    status = response.getStatusCode();
                    if (HttpStatus.OK.equals(status))
                    {
                            return response.getBody();
                    }
            } catch (HttpClientErrorException e)
            {
                    if (HttpStatus.NOT_FOUND.equals(e.getStatusCode()))
                    {
                            throw new MyServiceNotFoundException();
                    }
                    else
                    {
                            Log.e(getClass().toString(), String.format("Error %s request, status[%s]", method.toString(), e.getStatusCode()), e);
                    }
            } catch (Exception e)
            {
                    Log.e(getClass().toString(), String.format("Error %s request, status: %s", method.toString(), status), e);
            }
            return null;
    }

    /**
     * 
     * @return
     */
    private HttpEntity<?> getRequestEntity()
    {
            if (this.requestEntity == null)
            {
                    this.requestEntity = new HttpEntity<Object>(headers);
            }
            return requestEntity;
    }

    /**
     * 
     * @return
     */
    private URI toUri()
    {
            return this.builder.build().toUri();
    }

    /**
     * 
     * @return
     */
    private Gson getGson()
    {
            return new GsonBuilder().create();
    }

    /**
     * 
     * @return
     */
    public HttpHeaders getHeaders()
    {
            return headers;
    }

}
Run Code Online (Sandbox Code Playgroud)

我使用ListenerFileSystemResource而不是FileSystemResource并且有效。希望这对将来的人有帮助,因为我没有找到有关 Spring 框架的任何信息。