You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							123 lines
						
					
					
						
							3.1 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							123 lines
						
					
					
						
							3.1 KiB
						
					
					
				
								package command
							 | 
						|
								
							 | 
						|
								import (
							 | 
						|
									"context"
							 | 
						|
									"fmt"
							 | 
						|
									"net/url"
							 | 
						|
									"os"
							 | 
						|
									"strings"
							 | 
						|
								
							 | 
						|
									"github.com/seaweedfs/seaweedfs/weed/filer"
							 | 
						|
									"github.com/seaweedfs/seaweedfs/weed/pb"
							 | 
						|
									"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
							 | 
						|
									"github.com/seaweedfs/seaweedfs/weed/wdclient"
							 | 
						|
									"google.golang.org/grpc"
							 | 
						|
								
							 | 
						|
									"github.com/seaweedfs/seaweedfs/weed/security"
							 | 
						|
									"github.com/seaweedfs/seaweedfs/weed/util"
							 | 
						|
								)
							 | 
						|
								
							 | 
						|
								var (
							 | 
						|
									filerCat FilerCatOptions
							 | 
						|
								)
							 | 
						|
								
							 | 
						|
								type FilerCatOptions struct {
							 | 
						|
									grpcDialOption grpc.DialOption
							 | 
						|
									filerAddress   pb.ServerAddress
							 | 
						|
									filerClient    filer_pb.SeaweedFilerClient
							 | 
						|
									output         *string
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func (fco *FilerCatOptions) GetLookupFileIdFunction() wdclient.LookupFileIdFunctionType {
							 | 
						|
									return func(ctx context.Context, fileId string) (targetUrls []string, err error) {
							 | 
						|
										vid := filer.VolumeId(fileId)
							 | 
						|
										resp, err := fco.filerClient.LookupVolume(ctx, &filer_pb.LookupVolumeRequest{
							 | 
						|
											VolumeIds: []string{vid},
							 | 
						|
										})
							 | 
						|
										if err != nil {
							 | 
						|
											return nil, err
							 | 
						|
										}
							 | 
						|
										locations := resp.LocationsMap[vid]
							 | 
						|
										for _, loc := range locations.Locations {
							 | 
						|
											targetUrls = append(targetUrls, fmt.Sprintf("http://%s/%s", loc.Url, fileId))
							 | 
						|
										}
							 | 
						|
										return
							 | 
						|
									}
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func init() {
							 | 
						|
									cmdFilerCat.Run = runFilerCat // break init cycle
							 | 
						|
									filerCat.output = cmdFilerCat.Flag.String("o", "", "write to file instead of stdout")
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								var cmdFilerCat = &Command{
							 | 
						|
									UsageLine: "filer.cat [-o <file>] http://localhost:8888/path/to/file",
							 | 
						|
									Short:     "copy one file to local",
							 | 
						|
									Long: `read one file to stdout or write to a file
							 | 
						|
								
							 | 
						|
								`,
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func runFilerCat(cmd *Command, args []string) bool {
							 | 
						|
								
							 | 
						|
									util.LoadSecurityConfiguration()
							 | 
						|
								
							 | 
						|
									if len(args) == 0 {
							 | 
						|
										return false
							 | 
						|
									}
							 | 
						|
									filerSource := args[len(args)-1]
							 | 
						|
								
							 | 
						|
									filerUrl, err := url.Parse(filerSource)
							 | 
						|
									if err != nil {
							 | 
						|
										fmt.Printf("The last argument should be a URL on filer: %v\n", err)
							 | 
						|
										return false
							 | 
						|
									}
							 | 
						|
									urlPath := filerUrl.Path
							 | 
						|
									if strings.HasSuffix(urlPath, "/") {
							 | 
						|
										fmt.Printf("The last argument should be a file: %v\n", err)
							 | 
						|
										return false
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									filerCat.filerAddress = pb.ServerAddress(filerUrl.Host)
							 | 
						|
									filerCat.grpcDialOption = security.LoadClientTLS(util.GetViper(), "grpc.client")
							 | 
						|
								
							 | 
						|
									dir, name := util.FullPath(urlPath).DirAndName()
							 | 
						|
								
							 | 
						|
									writer := os.Stdout
							 | 
						|
									if *filerCat.output != "" {
							 | 
						|
								
							 | 
						|
										fmt.Printf("saving %s to %s\n", filerSource, *filerCat.output)
							 | 
						|
								
							 | 
						|
										f, err := os.OpenFile(*filerCat.output, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
							 | 
						|
										if err != nil {
							 | 
						|
											fmt.Printf("open file %s: %v\n", *filerCat.output, err)
							 | 
						|
											return false
							 | 
						|
										}
							 | 
						|
										defer f.Close()
							 | 
						|
										writer = f
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									pb.WithFilerClient(false, util.RandomInt32(), filerCat.filerAddress, filerCat.grpcDialOption, func(client filer_pb.SeaweedFilerClient) error {
							 | 
						|
								
							 | 
						|
										request := &filer_pb.LookupDirectoryEntryRequest{
							 | 
						|
											Name:      name,
							 | 
						|
											Directory: dir,
							 | 
						|
										}
							 | 
						|
										respLookupEntry, err := filer_pb.LookupEntry(context.Background(), client, request)
							 | 
						|
										if err != nil {
							 | 
						|
											return err
							 | 
						|
										}
							 | 
						|
								
							 | 
						|
										if len(respLookupEntry.Entry.Content) > 0 {
							 | 
						|
											_, err = writer.Write(respLookupEntry.Entry.Content)
							 | 
						|
											return err
							 | 
						|
										}
							 | 
						|
								
							 | 
						|
										filerCat.filerClient = client
							 | 
						|
								
							 | 
						|
										return filer.StreamContent(&filerCat, writer, respLookupEntry.Entry.GetChunks(), 0, int64(filer.FileSize(respLookupEntry.Entry)))
							 | 
						|
								
							 | 
						|
									})
							 | 
						|
								
							 | 
						|
									return true
							 | 
						|
								}
							 |